package com.managertrade.dto.vo;

import lombok.Data;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;


public class KlineWithIndicators {
    /**
     * 时间戳（毫秒）
     */
    private long timestamp;

    /**
     * 开盘价
     */
    private double open;

    /**
     * 最高价
     */
    private double high;

    /**
     * 最低价
     */
    private double low;

    /**
     * 收盘价
     */
    private double close;

    /**
     * 成交量
     */
    private double volume;

    // ==== 以下是各类技术指标 ====

    /**
     * EMA（指数移动平均）7周期
     */
    private Double ema7;

    /**
     * EMA（指数移动平均）21周期
     */
    private Double ema21;

    /**
     * MACD DIF 值（快线 - 慢线）
     */
    private Double macd;

    /**
     * MACD DEA 值（信号线）
     */
    private Double signal;

    /**
     * MACD 柱状图（macd - signal）
     */
    private Double histogram;

    /**
     * BOLL 上轨（布林带上限）
     */
    private Double bollUpper;

    /**
     * BOLL 中轨（一般为N日均线）
     */
    private Double bollMiddle;

    /**
     * BOLL 下轨（布林带下限）
     */
    private Double bollLower;


    // 新增字段
    private String symbol;       // 币种名称，例如 "ETH-USDT"
    private String period;       // 周期名称，例如 "4h"
    private String uniqueId;     // 唯一ID = symbol + period + timestamp

    /**
     * 可读时间
     */
    private String datetime;

    // ==== 新增字段（标准MACD结构）
    private Double macdDiff;
    // 快线
    private Double macdDea;

    // 慢线 柱子 (diff - dea) * 2
    private Double macdBar;

    public Double getMacdDiff() {
        return macdDiff;
    }

    public void setMacdDiff(Double macdDiff) {
        this.macdDiff = macdDiff;
    }

    public Double getMacdDea() {
        return macdDea;
    }

    public void setMacdDea(Double macdDea) {
        this.macdDea = macdDea;
    }

    public Double getMacdBar() {
        return macdBar;
    }

    public void setMacdBar(Double macdBar) {
        this.macdBar = macdBar;
    }

    public KlineWithIndicators() {
    }

    private String generateUniqueId() {
        return symbol + "_" + period + "_" + timestamp;
    }

    // getter 和 setter
    public long getTimestamp() {
        return timestamp;
    }

    public void setTimestamp(long timestamp) {
        this.timestamp = timestamp;
        // 同步生成可读时间
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        this.datetime = sdf.format(new Date(timestamp));
        this.uniqueId = generateUniqueId(); // 更新时间戳时更新 uniqueId

    }

    public void setDatetime(String datetime) {
        this.datetime = datetime;
    }

    public String getDatetime() {
        return datetime;
    }

    public double getOpen() {
        return open;
    }

    public void setOpen(double open) {
        this.open = open;
    }

    public double getHigh() {
        return high;
    }

    public void setHigh(double high) {
        this.high = high;
    }

    public double getLow() {
        return low;
    }

    public void setLow(double low) {
        this.low = low;
    }

    public double getClose() {
        return close;
    }

    public void setClose(double close) {
        this.close = close;
    }

    public double getVolume() {
        return volume;
    }

    public Double getEma7() {
        return ema7;
    }

    public Double getEma21() {
        return ema21;
    }

    public Double getMacd() {
        return macd;
    }

    public Double getSignal() {
        return signal;
    }

    public Double getHistogram() {
        return histogram;
    }

    public Double getBollUpper() {
        return bollUpper;
    }

    public Double getBollMiddle() {
        return bollMiddle;
    }

    public Double getBollLower() {
        return bollLower;
    }

    public void setVolume(double volume) {
        this.volume = volume;
    }

    public String getSymbol() {
        return symbol;
    }

    public void setSymbol(String symbol) {
        this.symbol = symbol;
        this.uniqueId = generateUniqueId(); // 更新 symbol 时同步更新 uniqueId
    }

    public String getPeriod() {
        return period;
    }

    public void setEma7(Double ema7) {
        this.ema7 = ema7;
    }

    public void setEma21(Double ema21) {
        this.ema21 = ema21;
    }

    public void setMacd(Double macd) {
        this.macd = macd;
    }

    public void setSignal(Double signal) {
        this.signal = signal;
    }

    public void setHistogram(Double histogram) {
        this.histogram = histogram;
    }

    public void setBollUpper(Double bollUpper) {
        this.bollUpper = bollUpper;
    }

    public void setBollMiddle(Double bollMiddle) {
        this.bollMiddle = bollMiddle;
    }

    public void setBollLower(Double bollLower) {
        this.bollLower = bollLower;
    }

    public void setUniqueId(String uniqueId) {
        this.uniqueId = uniqueId;
    }

    public void setPeriod(String period) {
        this.period = period;
        this.uniqueId = generateUniqueId(); // 更新 period 时同步更新 uniqueId
    }

    public String getUniqueId() {
        return uniqueId;
    }

    public static void calculateIndicators(List<KlineWithIndicators> klines) {
        if (klines == null || klines.isEmpty()) return;
        final int shortPeriod = 12;
        final int longPeriod = 26;
        final int signalPeriod = 9;
        Double emaShort = null;
        Double emaLong = null;
        Double dea = 0.0;
        for (int i = 0; i < klines.size(); i++) {
            KlineWithIndicators k = klines.get(i);
            double close = k.getClose();
            // EMA7, EMA21
            if (i == 0) {
                k.setEma7(close);
                k.setEma21(close);
            } else {
                double prevEma7 = klines.get(i - 1).getEma7();
                double prevEma21 = klines.get(i - 1).getEma21();
                k.setEma7(calcEma(close, prevEma7, 7));
                k.setEma21(calcEma(close, prevEma21, 21));
            } // MACD
            if (emaShort == null) {
                emaShort = close;
                emaLong = close;
            } else {
                emaShort = calcEma(close, emaShort, shortPeriod);
                emaLong = calcEma(close, emaLong, longPeriod);
            }
            double diff = emaShort - emaLong;
            dea = dea + (2.0 / (signalPeriod + 1)) * (diff - dea);
            double macd = 2 * (diff - dea);
            k.setMacdDiff(diff);
            k.setMacdDea(dea);
            k.setMacd(macd);
        }
    }

    /**
     * 单步 EMA
     */
    private static double calcEma(double price, double prevEma, int period) {
        double alpha = 2.0 / (period + 1);
        return alpha * price + (1 - alpha) * prevEma;
    }
}
